#ifndef __CLIENT_MANAGER_H__
#define __CLIENT_MANAGER_H__

#include <crypt.h>
#include <random>
#include <mutex>
#include <map>
#include <set>
#include "../database/DBManager.hpp" // 数据库操作
#include "../log/xdgspdlog.hpp" // 日志文件


// 定义接口请求类型枚举（从101开始）
enum RequestType {
    REQUEST_GETSALT = 101,      // 获取盐值
    REQUEST_REGISTER,           // 注册
    REQUEST_LOGIN,            // 登录
    REQUEST_JOINRTSP, // 加入到获取rtsp实时流的队列中
    REQUEST_QUITRTSP, // 退出rtsp实时流队列
    REQUEST_VIDEOSTREAM, // 视频流数据
};


struct UserInfo
{
    bool isLogin; // 是否登录
    std::string username; // 用户名
    std::string pwd_hash; // 密码哈希值
    std::string salt; // 盐值
    std::string ip; // 用户IP
    unsigned short port; // 用户端口
};


class UsersPull
{
public:
    // 获取单例实例的静态方法
    static UsersPull& getInstance()
    {
        static UsersPull pull; // C++11 标准规定了局部静态变量的初始化是线程安全的。
        return pull;
    }

    // 添加到推流队列中
    void addUser(int fd)
    {
        m_mutex.lock();
        m_users.insert(fd);
        m_mutex.unlock();
    }

    // 从推流队列中删除
    void delUser(int fd)
    {
        m_mutex.lock();
        m_users.erase(fd);
        m_mutex.unlock();
    }

    // 获取所有用户
    std::vector<int> getUsers()
    {
        m_mutex.lock();
        std::vector<int> users;
        users.reserve(m_users.size());
        for (auto fd : m_users) { users.push_back(fd); }
        m_mutex.unlock();
        return users;
    }


    // 获取用户数量
    int getUserCount(){
        return m_users.size();
    }


private:
    // 私有构造函数，防止外部实例化
    UsersPull() = default;
    
    // 删除拷贝构造函数和赋值操作符
    UsersPull(const UsersPull&) = delete;
    UsersPull& operator=(const UsersPull&) = delete;
    
    std::set<int> m_users;
    std::mutex m_mutex;

};



class UsersInfoManager
{
public:
    // 获取单例实例的静态方法
    static UsersInfoManager& getInstance()
    {
        static UsersInfoManager instance; // C++11 标准规定了局部静态变量的初始化是线程安全的。
        return instance;
    }

    // 添加或更新用户信息
    void addUser(int fd, const UserInfo& userInfo)
    {
        m_mutex.lock();
        m_usersInfo[fd] = userInfo;
        m_mutex.unlock();
    }

    // 删除用户
    void delUser(int fd)
    {
        m_mutex.lock();
        m_usersInfo.erase(fd);
        m_mutex.unlock();
    }

    // 获取用户信息
    bool getUser(int fd, UserInfo& userInfo)
    {
        m_mutex.lock();
        auto it = m_usersInfo.find(fd);
        if (it != m_usersInfo.end()) {
            userInfo = it->second;
            m_mutex.unlock();
            return true;
        }
        m_mutex.unlock();
        return false;
    }

    // 获取用户盐值
    std::string getUserSalt(int fd)
    {
        auto it = m_usersInfo.find(fd);
        if (it != m_usersInfo.end()) {
            return it->second.salt;
        }

        return "";
    }

    // 检查用户是否存在
    bool userExists(int fd)
    {
        m_mutex.lock();
        bool exists = (m_usersInfo.find(fd) != m_usersInfo.end());
        m_mutex.unlock();
        return exists;
    }


    // 检查用户是否登录
    bool userLogin(int fd)
    {
        m_mutex.lock();
        bool exists = ( (m_usersInfo.find(fd) != m_usersInfo.end() ) && m_usersInfo[fd].isLogin);
        m_mutex.unlock();
        return exists;
    }

    // 根据用户名查找fd，-1表示未找到
    int findUserByUsername(const std::string& username)
    {
        m_mutex.lock();
        for (const auto& pair : m_usersInfo) {
            if (pair.second.username == username) {
                int fd = pair.first;
                m_mutex.unlock();
                return fd;
            }
        }
        m_mutex.unlock();
        return -1;  // 返回-1表示未找到
    }
    
    // 获取用户数量
    size_t getUserCount()
    {
        m_mutex.lock();
        size_t count = m_usersInfo.size();
        m_mutex.unlock();
        return count;
    }
    
    // 清空所有用户信息
    void clearAllUsers()
    {
        m_mutex.lock();
        m_usersInfo.clear();
        m_mutex.unlock();
    }

private:
    // 私有构造函数，防止外部实例化
    UsersInfoManager() = default;
    
    // 删除拷贝构造函数和赋值操作符
    UsersInfoManager(const UsersInfoManager&) = delete;
    UsersInfoManager& operator=(const UsersInfoManager&) = delete;
    
    std::map<int, UserInfo> m_usersInfo;
    std::mutex m_mutex;

};




/**
 * 生成随机字符字符串。
 *
 * @param charCount 要生成的字符数量。
 * @param mode 获取模式：1-数字, 2-小写字母, 4-大写字母, 8-特殊字符, 16-UTF8中文字符
 *              可以使用位或(|)组合多种模式，默认为1（只包含数字）。
 * @return 返回生成的随机字符串。
 */
std::string randomStr(int charCount, int mode = 1|2|4)
{
    std::string result;
    std::random_device rd;
    std::mt19937 gen(rd());

    // 检查是否包含中文字符
    bool hasChinese = (mode & 16) != 0;

    // 如果只包含中文字符
    if (mode == 16)
    {
        // 常用汉字范围 U+4E00 到 U+9FFF
        const unsigned int chineseStart = 0x4E00;
        const unsigned int chineseEnd = 0x9FFF; // 扩大范围以获取更多汉字
        std::uniform_int_distribution<unsigned int> chineseDis(chineseStart, chineseEnd);

        for (int i = 0; i < charCount; ++i)
        {
            unsigned int codePoint = chineseDis(gen);

            // 将Unicode码点转换为UTF-8编码
            if (codePoint <= 0x7F)
            {
                result += static_cast<char>(codePoint);
            }
            else if (codePoint <= 0x7FF)
            {
                result += static_cast<char>(0xC0 | (codePoint >> 6));
                result += static_cast<char>(0x80 | (codePoint & 0x3F));
            }
            else if (codePoint <= 0xFFFF)
            {
                result += static_cast<char>(0xE0 | (codePoint >> 12));
                result += static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F));
                result += static_cast<char>(0x80 | (codePoint & 0x3F));
            }
        }
        return result;
    }

    // 处理其他字符类型
    std::string otherChars;
    if (mode & 1)
        otherChars += "0123456789"; // 数字
    if (mode & 2)
        otherChars += "abcdefghijklmnopqrstuvwxyz"; // 小写字母
    if (mode & 4)
        otherChars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // 大写字母
    if (mode & 8)
        otherChars += "!@#$%^&*()-_=+[]{}|;:,.<>?"; // 特殊字符

    // 如果没有选择任何其他字符集，默认使用数字
    if (otherChars.empty())
        otherChars = "0123456789";

    // 如果同时包含中文字符和其他字符
    if (hasChinese)
    {
        const unsigned int chineseStart = 0x4E00;
        const unsigned int chineseEnd = 0x9FFF;
        std::uniform_int_distribution<unsigned int> chineseDis(chineseStart, chineseEnd);

        for (int i = 0; i < charCount; ++i)
        {
            // 50%概率生成中文字符，50%概率生成其他字符
            if (gen() % 2 == 0)
            {
                // 生成中文字符
                unsigned int codePoint = chineseDis(gen);

                if (codePoint <= 0x7F)
                {
                    result += static_cast<char>(codePoint);
                }
                else if (codePoint <= 0x7FF)
                {
                    result += static_cast<char>(0xC0 | (codePoint >> 6));
                    result += static_cast<char>(0x80 | (codePoint & 0x3F));
                }
                else if (codePoint <= 0xFFFF)
                {
                    result += static_cast<char>(0xE0 | (codePoint >> 12));
                    result += static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F));
                    result += static_cast<char>(0x80 | (codePoint & 0x3F));
                }
            }
            else
            {
                // 生成其他字符
                std::uniform_int_distribution<> charDis(0, otherChars.size() - 1);
                result += otherChars[charDis(gen)];
            }
        }
    }
    else
    {
        // 不包含中文，只包含其他字符
        std::uniform_int_distribution<> charDis(0, otherChars.size() - 1);
        for (int i = 0; i < charCount; ++i)
        {
            result += otherChars[charDis(gen)];
        }
    }

    return result;
}

/**
 * 生成 yescrypt 哈希值
 * @param password 原始密码（字符串）
 * @param salt 随机盐值（字符串，长度 16）
 * @return 分配的哈希字符串（格式：$5$rounds=5000$sqlt$hash...），失败返回 NULL
 */
std::string yescrypt_hash(const char *password, const char *salt)
{
    if (password == nullptr || salt == nullptr) { return NULL; }

    std::string setting_prefix = "$5$rounds=5000$"; // 
    setting_prefix += salt;
    setting_prefix += "$";

    // 调用 libcrypt 的 crypt 函数生成 yescrypt 哈希
    std::string hash = crypt(password, setting_prefix.c_str());

    return hash;
}

/**
 * 验证密码与 yescrypt 哈希是否匹配
 * @param password 原始密码
 * @param stored_hash 存储的 yescrypt 哈希字符串（如 $5$rounds=5000$sqlt$hash...）
 * @return 匹配返回 1，不匹配返回 0，错误返回 -1
 */
int yescrypt_verify(const char *password, const char *stored_hash)
{
    if (password == NULL || stored_hash == NULL) { return -1; }

    // 用存储的哈希作为 setting 调用 crypt，自动提取盐值和参数
    char *computed_hash = crypt(password, stored_hash);
    if (computed_hash == NULL) { return -1; }

    // 比较哈希（constant-time 比较防时序攻击）
    return (strcmp(computed_hash, stored_hash) == 0) ? 1 : 0;
}




// 账号验证成功返回其盐值，无此账号生成新的盐值
inline std::string interface_getSalt(std::shared_ptr<xdg::TcpContext> context, const std::string username)
{ 
    std::string salt = DBqueryUserExists(username); // 查询用户是否存在
    nlohmann::json j;
    j["type"] = 101;
    j["data_size"] = 0;
    
    // 数据库用户不存在，生成随机盐值并保存到该 fd 的结构体信息中
    if(salt.empty()){
        j["success"] = false;
        std::string salt;
        struct UserInfo user;

        if(UsersInfoManager::getInstance().userExists( context->getFd() ) ){
            // 在线用户存在，先获取该用户信息，更新盐值后保存
            UsersInfoManager::getInstance().getUser(context->getFd(), user);
            user.salt.empty() ? salt = randomStr(16) : salt = user.salt;
            user.salt = salt;

            LOG_CONSOLE_INFO("[接口 - 获取盐值] 数据库不存在该用户，UsersInfoManager中存在该用户，返回盐值");

        }else{
            // 在线用户不存在，创建用户信息并保存
            salt = randomStr(16);

            user.isLogin = false;
            user.username = username;
            user.pwd_hash = "";
            user.salt = salt;
            user.ip = context->clientIp();
            user.port = context->clientPort();
            
            LOG_CONSOLE_INFO("[接口 - 获取盐值] 数据库不存在该用户，UsersInfoManager中不存在该用户，新建盐值");

        }

        UsersInfoManager::getInstance().addUser(context->getFd(), user);

        j["salt"] = salt;
        return j.dump(1);
    }

    // 数据库用户存在，返回数据库中的盐值并保存到该 fd 的结构体信息中
    j["success"] = true;
    j["salt"] = salt;

    struct UserInfo user;
    user.isLogin = false;
    user.username = username;
    user.pwd_hash = "";
    user.salt = j["salt"];
    user.ip = context->clientIp();
    user.port = context->clientPort();
    UsersInfoManager::getInstance().addUser(context->getFd(), user);

    LOG_CONSOLE_INFO("[接口 - 获取盐值] 数据库存在该用户，获取用户盐值成功");
    return j.dump(1);
}

// 注册
inline std::string interface_register(std::shared_ptr<xdg::TcpContext> context, const std::string username, const std::string pwd)
{ 
    std::string user_is = DBqueryUserExists(username); // 查询用户是否存在
    nlohmann::json j;
    j["type"] = 102;
    j["data_size"] = 0;

    // 不为空，说明用户已经存在，直接返回失败
    if( !user_is.empty() ){
        j["success"] = false;
        j["tip"] = "欲注册用户名已存在。";
        LOG_CONSOLE_INFO("[接口 - 注册] 欲注册用户已存在");

        return j.dump(1);
    }

    // 欲注册用户不存在。可以进行新注册。先获取用户盐值。获取不到时，生成一个
    std::string salt;
    struct UserInfo user;
    UsersInfoManager::getInstance().getUser(context->getFd(), user);

    user.salt.empty() ? salt = randomStr(16) : salt = user.salt;
    user.salt = salt; // 保险，更新一下
    UsersInfoManager::getInstance().addUser(context->getFd(), user);

    // 向数据库中注册用户
    if(DBregisterUser(username, pwd, salt)){
        j["success"] = true;
        j["tip"] = "";
        LOG_CONSOLE_INFO("[接口 - 注册] 用户：{}    注册成功",username);
        return j.dump(1);
    }
    j["success"] = false;
    j["tip"] = "系统错误，注册失败。";
    LOG_CONSOLE_INFO("[接口 - 注册] 用户：{}    注册失败",username);
    return j.dump(1);

}

// 登录
inline std::string interface_login(std::shared_ptr<xdg::TcpContext> context, const std::string username, const std::string pwd)
{ 
    bool success = DBverifyUserLogin(username, pwd);
    nlohmann::json j;
    j["type"] = 103;
    j["data_size"] = 0;

    if(success){
        // 用户名与密码匹配成功。将登录信息保存到该 fd 的结构体信息中
        struct UserInfo user;
        UsersInfoManager::getInstance().getUser(context->getFd(), user);
        user.username = username;
        user.pwd_hash = pwd;
        user.isLogin = true;
        UsersInfoManager::getInstance().addUser(context->getFd(), user); // 更新在线列表

        j["success"] = true;

        LOG_CONSOLE_INFO("[接口 - 登录] 用户：{}    登录成功",username);
        return j.dump(1);
    }

    j["success"] = false;
    LOG_CONSOLE_INFO("[接口 - 登录] 用户：{}    登录失败",username);
    return j.dump(1);
}


// 加入到推流队列
inline std::string interface_addpull(std::shared_ptr<xdg::TcpContext> context, const std::string username)
{ 
    int fd = UsersInfoManager::getInstance().findUserByUsername(username);
    bool success = UsersInfoManager::getInstance().userLogin(fd);
    nlohmann::json j;
    j["type"] = 104;
    j["data_size"] = 0;
    
    if (success)
    {
        UsersPull::getInstance().addUser(context->getFd());
        j["success"] = true;
        LOG_CONSOLE_INFO("[接口 - 加入推流] 用户：{}    加入成功",username);
        return j.dump(1);
    }
    j["success"] = false;
    LOG_CONSOLE_INFO("[接口 - 加入推流] 用户：{}    加入失败，用户未登录",username);
    j["tip"] = "用户未登录";
    return j.dump(1);

}

// 从推流队列中删除
inline void interface_delpull(std::shared_ptr<xdg::TcpContext> context)
{ 
    UsersPull::getInstance().delUser(context->getFd());
}







#endif // __CLIENT_MANAGER_H__